﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using IView;
using DataTransferObject;
using Engine;

namespace Presenter
{
    /*
     * sẽ được thiết kế tiếp sau này
     * dùng để xử lý các yêu cầu từ TaskForm
     */
    /// <summary>
    /// 
    /// </summary>
    public class PresenterTaskForm : Presenter
    {
        #region Internal class
        public class ExternalConstraints
        {
            public static string NO_CONSTRAINT = string.Empty;
            public static string FINISH_ON = "Finish on";
            public static string FINISH_ON_OR_BEFORE = "Finish on or before";
            public static string START_ON = "Start on";
            public static string START_ON_OR_AFTER = "Start on or after";
        }
        #endregion

        #region Attributes
        private ITaskForm iTaskFormView;
        private String pathToLoadConfig;

        private JskeEngine jskeEngine;
        private SystemConfiguration sysConfig;

        #endregion

        #region Constructors
        /// <summary>
        /// Initializes a new instance of the <see cref="PresenterTaskForm"/> class.
        /// </summary>
        /// <param name="iTaskFormView">The i task form view.</param>
        public PresenterTaskForm(ITaskForm iTaskFormView, int dataAccessMode)
        {
            Presenter.changeDataServiceMode(dataAccessMode);
            this.iTaskFormView = iTaskFormView;
            jskeEngine = JskeEngine.getInstance(dataServiceMode);
            jskeEngine.PathForSystemConfigFile = iTaskFormView.GetPathToLoadSystemConfig();
            jskeEngine.LoadSystemConfigFromFileToEngine();
            this.sysConfig = jskeEngine.SystemConfiguration;
            iTaskFormView.SetWorkingHourName(GetListOfWorkingHourName());
            iTaskFormView.SetProjectNamesForDDL(GetListOfProjectName());
        }

        #endregion

        #region Public Methods and Properties

        /// <summary>
        /// Populates the task object into form.
        /// </summary>
        /// <param name="t">The t.</param>
        public void PopulateTaskObjectIntoForm(Task t)
        {
            iTaskFormView.SetTaskName(t.Name);
            iTaskFormView.SetPriority(t.Priority + "");
            iTaskFormView.SetTotalWork(t.TotalWork);
            iTaskFormView.SetProjectName(t.ProjectName);
            iTaskFormView.SetWorkingHourID(t.WorkingHourID);
            iTaskFormView.SetRemainingTime(t.RemainTime);
            iTaskFormView.SetStartDate(t.ScheduledStartDate);
            iTaskFormView.SetEndDate(t.ScheduledEndDate);
            iTaskFormView.SetStatusID(t.TaskStatusIndex);
            iTaskFormView.SetTaskListPrecedence(t.PredecessorIDs);
            iTaskFormView.SetMinimumTimeSplit(t.MinimumTimeSplit);
            iTaskFormView.SetTaskNotes(t.Notes);
            iTaskFormView.setStartOnOrAfter(t.StartOnOrAfter);
            if (!t.DueDate.Equals(DateTime.MaxValue))
            {
                iTaskFormView.SetTaskExternalConstraint(ExternalConstraints.FINISH_ON_OR_BEFORE, t.DueDate);
            }
        }

        /// <summary>
        /// Saves the task to list.
        /// </summary>
        /// <param name="task">The task.</param>
        /// <returns></returns>
        public void AddTaskToEngine(Task task)
        {
            jskeEngine.AddTaskToTaskList(task);
        }

        /// <summary>
        /// Saves the task to list.
        /// </summary>
        /// <param name="task">The task.</param>
        /// <returns></returns>
        public void DeleteTaskFromEngine(Task task)
        {
            jskeEngine.DeleteTaskFromEngine(task);
        }

        /// <summary>
        /// Cập nhập thông tin task sau khi đã nhấn Ok từ TaskForm. Cần chú ý là việc cập nhập precedence constraint được thực hiện
        /// ngay tại TaskForm, còn các thuộc tính còn lại dc cập nhập tại PresenterTaskForm
        /// </summary>
        /// <param name="task">The task.</param>
        public void UpdateTaskToEngine(Task task)
        {
            task.Name = iTaskFormView.GetTaskName();
            try
            {
                task.TotalWork = iTaskFormView.GetTotalWork();
            }
            catch (FormatException fe)
            {
                throw new FormatException("Total work must be a number " + fe.Message);
            }

            try
            {
                if (iTaskFormView.GetActualWork() > iTaskFormView.GetTotalWork())
                {
                    throw new InvalidOperationException("Actual work mus be larger than total work");
                }
                if (iTaskFormView.GetActualWork() == 0)
                {
                    task.RemainTime = task.TotalWork;
                }
                else
                {
                    task.RemainTime = task.TotalWork - iTaskFormView.GetActualWork();
                }
            }
            catch (FormatException fe)
            {
                throw new FormatException("Actual work must be a number " + fe.Message);
            }
            task.MinimumTimeSplit = iTaskFormView.GetMinimumTimeSplit();
            task.ProjectName = iTaskFormView.GetProjectName();
            task.ProjectID = iTaskFormView.GetProjectID();
            task.WorkingHourID = iTaskFormView.GetWorkingHourID();
            task.Priority = iTaskFormView.GetPriority();
            task.TaskStatusIndex = iTaskFormView.GetStatusID();
            task.DueDate = iTaskFormView.GetDueDate();
            task.Notes = iTaskFormView.GetNotes();
            task.StartOnOrAfter = iTaskFormView.getStartOnOrAfter();
            jskeEngine.updateTaskList(task);
        }

        /// <summary>
        /// Gets the unconstrained tasks to create dependent constraint between tasks.
        /// </summary>
        /// <returns></returns>
        public List<Task> GetUnconstrainedTasks()
        {
            List<Task> originTaskList =  jskeEngine.TaskList.GetTaskList;
            List<Task> avaiTaskList = new List<Task>();
            foreach (Task t in originTaskList)
            {
                if (!t.IsHasConstraint())
                {
                    avaiTaskList.Add(t);
                }
            }
            return avaiTaskList;
        }

        public String PathToLoadConfig
        {
            get { return this.pathToLoadConfig; }
            set { this.pathToLoadConfig = value; }
        }

        #endregion

        #region Private methods
        private List<String> GetListOfWorkingHourName()
        {
            List<String> result = new List<String>();

            for (int i = 0; i < sysConfig.TabWorkingHoursData.ListOfWorkingHourItems.Count; i++)
            {
                String tmp;
                tmp = sysConfig.TabWorkingHoursData.ListOfWorkingHourItems[i].WorkingHourName;
                result.Add(tmp);
            }

            return result;
        }

        private List<String> GetListOfProjectName()
        {
            return sysConfig.TabProjectData.ListProjectName;
        }
        #endregion
    }
}
